package com.colin.library.base;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.IntRange;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.InputType;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;

import com.colin.library.help.StringHelp;
import com.colin.library.help.ToastHelp;
import com.colin.library.listener.IAlertCallBack;
import com.colin.library.listener.IAlertListCallBack;
import com.colin.library.listener.IAlertMultipleListCallBack;
import com.colin.library.manager.AppActivityManager;
import com.colin.library.other.AppException;
import com.colin.library.view.progress.MyProgressBar;

import java.util.HashMap;
import java.util.Map;

import static android.R.attr.inputType;

/**
 * Created by Colin on 2016/12/29.
 *
 *
 * 如何实现一个符合用户期待的app，你需要注意下面几点：
 * 当使用你的app的时候，不会因为有来电通话或者切换到其他app而导致程序crash。
 * 当用户没有激活某个组件的时候不要消耗宝贵的系统资源。
 * 当离开你的app并且一段时间后返回，不要丢失用户的使用进度。
 * 当设备发送屏幕旋转的时候，不会crash或者丢失用户的使用进度。
 *
 *
 * 在下面的课程中会介绍上图所示的几个生命状态。然而，其中只有三个状态是静态的，
 * 这三个状态下activity可以存在一段比较长的时间。(其它几个状态会很快就切换掉，停留的时间比较短暂)
 * Resumed：在这个状态，activity是在最前端的，用户可以与它进行交互。(通常也被理解为”running” 状态)
 * Paused：在这个状态，activity被另外一个activity所遮盖：另外的activity来到最前面，但是半透明的，不会覆盖整个屏幕。
 * 被暂停的activity不会再接受用户的输入且不会执行任何代码。(这里的不会执行任何代码并不代表了任何后台线程都不会工作)
 * Stopped：在这个状态, activity完全被隐藏，不被用户可见。可以认为是在后台。
 * 当stopped, activity实例与它的所有状态信息都会被保留，但是activity不能执行任何代码。
 * 其它状态 (Created与Started)都是短暂的，系统快速的执行那些回调函数并通过执行下一阶段的回调函数移动到下一个状态。
 * 也就是说，在系统调用onCreate(), 之后会迅速调用onStart(), 之后再迅速执行onResume()。上面就是基本的activity生命周期。
 */

public abstract class BaseActivity extends AppCompatActivity implements BaseView {
    /**
     * 基本数据
     */
    protected int mScreenWidth = 0;
    protected int mScreenHeight = 0;
    protected float mScreenDensity = 0.0f;

    protected int alert_what = -1; //当前提示框的值
    @Nullable
    protected Dialog dialog = null;
    @NonNull
    protected Map<Integer, Dialog> dialogMap = new HashMap<>();
    @Nullable
    protected static String TAG = null;
    @Nullable
    protected View activity_view = null;
    protected Toolbar toolbar;
    protected TextView text_toolbar_title;

    private boolean isLoading = false;//是否正在加载数据

    @Override
    public boolean isLoading() {
        return isLoading;
    }

    public void setLoading(boolean loading) {
        isLoading = loading;
    }

    /**
     * 其它状态 (Created与Started)都是短暂的，系统快速的执行那些回调函数并通过执行下一阶段的回调函数移动到下一个状态。
     * 也就是说，在系统调用onCreate(), 之后会迅速调用onStart(), 之后再迅速执行onResume()。上面就是基本的activity生命周期。
     *(onCreate里面尽量少做事情，避免程序启动太久都看不到界面)
     * 声明UI元素 ，定义成员变量，配置UI等
     *
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        TAG = this.getClass().getSimpleName();
        super.onCreate(savedInstanceState);
        //1:把界面放到栈中统一管理
        AppActivityManager.getInstance().addActivity(this);


        //2：得到activity基本参数
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        mScreenDensity = displayMetrics.density;
        mScreenHeight = displayMetrics.heightPixels;
        mScreenWidth = displayMetrics.widthPixels;
        //3:初始化布局
        if (initViewLayoutID() != 0) {
            setContentView(initViewLayoutID());
        } else {
            throw new AppException("布局文件加载失败");
        }

    }

    @Override
    protected void onRestart() {
        super.onRestart();
    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    /**
     * activity是在最前端的，用户可以与它进行交互。(通常也被理解为”running” 状态)
     */
    @Override
    protected void onResume() {
        super.onResume();
    }

    /**
     * 在这个状态，activity被另外一个activity所遮盖：另外的activity来到最前面，但是半透明的，不会覆盖整个屏幕。
     * 被暂停的activity不会再接受用户的输入且不会执行任何代码。(这里的不会执行任何代码并不代表了任何后台线程都不会工作)
     */
    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        closeAlert();
        setLoading(false);
        alert_what = -1;
        TAG = null;
        activity_view = null;
        super.onDestroy();
    }
    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        super.setContentView(layoutResID);
        initBaseView();
        initPresenter();
        initView();
        initData();
        initListener();
        if (!isLoading()) {
            initAsync();
        }
    }

    private void initBaseView() {
        this.activity_view = this.findViewById(R.id.app_activity_id);
        this.toolbar = (Toolbar) this.findViewById(R.id.toolbar);
        this.text_toolbar_title = (TextView) this.findViewById(R.id.text_toolbar_title);
        initToolBar();
    }

    /**
     * 初始化标题栏
     */
    private void initToolBar() {
        if (null != toolbar) {
            setSupportActionBar(toolbar);
            if (isHaveBack()) {
                getSupportActionBar().setDisplayHomeAsUpEnabled(isHaveBack());
                toolbar.setNavigationOnClickListener(new OnBackListener());
            }
            getSupportActionBar().setDisplayShowTitleEnabled(isHaveBack());
        }
    }

    @Override
    public void onBackPressed() {
        closeActivity();
        super.onBackPressed();
    }
    private long mExitTime = 0;//记录退出时间

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // 拦截MENU按钮点击事件，让他无任何操作
        if (keyCode == KeyEvent.KEYCODE_MENU) {
            return true;
        }
        //监听返回按钮
        if (keyCode == KeyEvent.KEYCODE_BACK) {//判断主界面
            if (this.getClass().getSimpleName().equals("MainActivity") && (System.currentTimeMillis() - mExitTime) > 2000) {
                toastShow(R.string.press_again_exit_app);
                mExitTime = System.currentTimeMillis();
            } else if (this.getClass().getSimpleName().equals("MainActivity")) {
                AppActivityManager.getInstance().clear();
                closeActivity();
            } else {
                onBackPressed();
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }


    /**
     * 隐藏键盘
     */
    @Override
    public void hideKeyword() {
        InputMethodManager imm = ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE));
        if (imm != null && getCurrentFocus() != null) {
            imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

    @Override
    public void setTitle(@NonNull String title) {
        if (null != toolbar) {
            if (null!=text_toolbar_title){
                this.text_toolbar_title.setText(title);
            }
            this.toolbar.setTitle(title);
        }
    }
    /**
     * 网络请求开始 开启网络请求的弹出框
     *
     * @param is_show_loading
     */
    @Override
    public void httpStart(boolean is_show_loading) {
        setLoading(true);
        if (is_show_loading && !isAlertShowing(ALERT_LOADING)) {
            this.alert_what = ALERT_LOADING;
            dialog = new MyProgressBar(this, getString(R.string.dialog_loading));
            dialog.setCancelable(false);
            dialogMap.put(this.alert_what, dialog);
            dialog.show();
        }
    }

    /**
     * 网络请求结束
     *
     * @param is_show_loading
     */
    @Override
    public void httpEnd(boolean is_show_loading) {
        setLoading(false);
        if (is_show_loading) {
            closeAlert(ALERT_LOADING);
        }
    }

    /**
     * 普通提示
     *
     * @param string_id
     */
    @Override
    public void toastShow(@StringRes int string_id) {
        toastShow(getString(string_id));
    }

    /**
     * 普通提示
     *
     * @param msg
     */
    @Override
    public void toastShow(@NonNull String msg) {
        //        防止遮盖虚拟按键
        if (!StringHelp.isEmpty(msg) && activity_view != null) {
            Snackbar.make(activity_view, msg, Snackbar.LENGTH_SHORT).show();
        } else if (activity_view == null && !StringHelp.isEmpty(msg)) {
            ToastHelp.showShort(msg);
        }
    }

    /**
     * 是否有弹出框显示
     *
     * @return
     */
    @Override
    public boolean isAlertShowing() {
        boolean isShowing = false;
        for (Map.Entry<Integer, Dialog> dialogEntry : dialogMap.entrySet()) {
            if (dialogEntry.getValue().isShowing()) {
                isShowing = true;
            }
        }
        return isShowing;
    }

    /**
     * 某个弹出框是否显示中
     *
     * @param alert_what
     * @return
     */
    @Override
    public boolean isAlertShowing(@IntRange int alert_what) {
        return dialogMap.get(alert_what) != null && dialogMap.get(alert_what).isShowing();
    }

    @Override
    public void alertShow(String message) {
        this.alertShow( getString(R.string.notice), message);
    }

    @Override
    public void alertShow(String title, String message) {
        this.alertShow(ALERT_PROMPT, title, message, null);
    }

    @Override
    public void alertShow(int alert_what, String message) {
        this.alertShow(alert_what, getString(R.string.notice), message, null);
    }

    @Override
    public void alertShow(int alert_what, String title, String message, final IAlertCallBack iAlertCallBack) {
        if (isAlertShowing(alert_what)) {
            return;
        }

        this.alert_what = alert_what;

        title = StringHelp.isEmpty(title) ? getString(R.string.notice) : title;
        message = StringHelp.isEmpty(message) ? getString(R.string.notice) : message;
        if (null == iAlertCallBack) {
            dialog = new android.support.v7.app.AlertDialog.Builder(this)
                    .setCancelable(false)
                    .setTitle(title)
                    .setMessage(message)
                    .setNeutralButton(R.string.iknow, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    }).create();
        } else {
            dialog = new android.support.v7.app.AlertDialog.Builder(this)
                    .setCancelable(false)
                    .setTitle(title)
                    .setMessage(message)
                    .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            if (iAlertCallBack != null) {
                                iAlertCallBack.alertCallBack(true, null);
                            }
                        }
                    }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            if (iAlertCallBack != null) {
                                iAlertCallBack.alertCallBack(false, null);
                            }
                        }
                    }).create();
        }
        dialogMap.put(this.alert_what, dialog);

        dialog.show();

    }

    @Override
    public void alertEdit(String title, String message, IAlertCallBack iAlertCallBack) {
        this.alertEdit(title, message, InputType.TYPE_CLASS_TEXT, iAlertCallBack);
    }

    @Override
    public void alertEdit(String title, String message, int inPutType, final IAlertCallBack iAlertCallBack) {
        if (isAlertShowing(ALERT_EDIT)) {
            return;
        }
        this.alert_what = ALERT_EDIT;

        View dialogView = LayoutInflater.from(this).inflate(R.layout.layout_dialog_edittext, null);
        final EditText edit_alert_show = (EditText) dialogView.findViewById(R.id.edit_alert_show);
        edit_alert_show.setInputType(inputType);
        edit_alert_show.setHint(message);
        dialog = new AlertDialog.Builder(this)
                .setView(dialogView)
                .setTitle(title)
                .setCancelable(false)
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        iAlertCallBack.alertCallBack(true, StringHelp.getText(edit_alert_show));
                    }
                })
                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        iAlertCallBack.alertCallBack(false, StringHelp.getText(edit_alert_show));
                        dialog.dismiss();
                    }
                })
                .create();

        dialogMap.put(this.alert_what, dialog);

        dialog.show();

    }

    @Override
    public void alertList(String[] array, IAlertListCallBack iAlertListCallBack) {
        this.alertList(getString(R.string.choose), -1, array, iAlertListCallBack);
    }

    @Override
    public void alertList(String title, int position, final String[] array, final IAlertListCallBack callBack) {
        if (isAlertShowing(ALERT_LIST)) {
            return;
        }
        this.alert_what = ALERT_LIST;
        final int[] dialog_choose_position = new int[1];
        final String[] dialog_choose_object = new String[1];

        dialog = new AlertDialog.Builder(this)
                .setCancelable(false)
                .setTitle(title)
                .setSingleChoiceItems(array, position, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int which) {
                        dialog_choose_position[0] = which;
                        dialog_choose_object[0] = array[which];
                    }
                })
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int which) {
                        dialog.dismiss();
                        if (callBack != null) {
                            callBack.alertCallBack(true, dialog_choose_position[0], dialog_choose_object[0]);
                        }
                    }
                })
                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int which) {
                        dialog.dismiss();
                    }
                }).create();
        android.view.WindowManager.LayoutParams p = dialog.getWindow().getAttributes();  //获取对话框当前的参数值
        p.height = (int) (mScreenHeight * 0.6);   //高度设置为屏幕的0.5
        dialog.getWindow().setAttributes(p);     //设置生效


        dialogMap.put(this.alert_what, dialog);

        dialog.show();


    }

    @Override
    public void alertMultiList(String[] array, IAlertMultipleListCallBack callBack) {
        this.alertMultipleList(getString(R.string.choose), null, array, callBack);
    }

    @Override
    public void alertMultipleList(String title, boolean[] positionArray, String[] array, final IAlertMultipleListCallBack callBack) {
        if (isAlertShowing(ALERT_LIST)) {
            return;
        }
        this.alert_what = ALERT_LIST;
        //初始化选中的值
        final boolean[] dialog_choose_position = new boolean[array.length];
        final String[] dialog_choose_object = new String[array.length];

        if (null == positionArray || positionArray.length != array.length) {
            positionArray = new boolean[array.length];
            for (int i = 0; i < array.length; i++) {
                positionArray[i] = false;
            }
        }

        for (int i = 0; i < positionArray.length; i++) {
            dialog_choose_position[i] = positionArray[i];
        }


        dialog = new AlertDialog.Builder(this)
                .setCancelable(false)
                .setTitle(title)
                .setMultiChoiceItems(array, positionArray, new DialogInterface.OnMultiChoiceClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                        dialog_choose_position[which] = isChecked;
                    }
                })
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int which) {
                        dialog.dismiss();
                        if (callBack != null) {
                            callBack.alertCallBack(true, dialog_choose_position, dialog_choose_object);
                        }
                    }
                })
                .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int which) {
                        dialog.dismiss();
                    }
                }).create();
        android.view.WindowManager.LayoutParams p = dialog.getWindow().getAttributes();  //获取对话框当前的参数值
        p.height = (int) (mScreenHeight * 0.6);   //高度设置为屏幕的0.5
        dialog.getWindow().setAttributes(p);     //设置生效

        dialogMap.put(this.alert_what, dialog);

        dialog.show();
    }


    /**
     * 关闭所有弹出框
     */
    @Override
    public void closeAlert() {
        for (Map.Entry<Integer, Dialog> dialogEntry : dialogMap.entrySet()) {
            dialogEntry.getValue().dismiss();
            dialogMap.remove(dialogEntry.getKey());
        }
        dialogMap.clear();
    }

    /**
     * 关闭指定弹出框
     */
    @Override
    public void closeAlert(@IntRange int alert_what) {
        if (isAlertShowing(alert_what) || null != dialogMap.get(alert_what)) {
            dialogMap.get(alert_what).dismiss();
            dialogMap.remove(alert_what);
        }
    }

    /**
     * 界面跳转
     *
     * @param target
     * @param bundle
     * @param closeSelf
     */
    @Override
    public void startActivity(@NonNull String target, @Nullable Bundle bundle, @NonNull boolean closeSelf) {
        Class clazz = null;
        try {
            clazz = Class.forName(target);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        if (clazz != null) {
            hideKeyword();
            if (closeSelf) {
                this.closeActivity();
            }
            Intent intent = new Intent(this, clazz);
            //android5.0之后隐式启动是禁止的；你需要加上这句代码
            intent.setPackage(getPackageName());
            if (bundle != null) {
                intent.putExtras(bundle);
            }
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            this.startActivity(intent);
            showOpenAnim();
        }
    }

    @Override
    public void startActivity(@NonNull Class<? extends Activity> target, @Nullable Bundle bundle, @NonNull boolean closeSelf) {
        hideKeyword();
        if (closeSelf) {
            this.closeActivity();
        }
        Intent intent = new Intent(this, target);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        this.startActivity(intent);
        showOpenAnim();
    }

    @Override
    public void startActivityForResult(@NonNull Class<? extends Activity> target, int requestCode, @NonNull Bundle bundle) {
        hideKeyword();
        Intent intent = new Intent(this, target);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        this.startActivityForResult(intent, requestCode);
        showOpenAnim();
    }

    /**
     * 关闭当前界面
     */
    @Override
    public void closeActivity() {
        hideKeyword();
        AppActivityManager.getInstance().removeActivity(this);
        this.finish();
        showCloseAnim();
    }


    /**
     * 启动界面：显示动画
     */
    protected void showOpenAnim() {
        this.overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
    }

    /**
     * 关闭界面：显示动画
     */
    protected void showCloseAnim() {
        this.overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
    }

    public class OnBackListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            onBackPressed();
        }
    }

    protected abstract boolean isHaveBack();
}
